The premise of our game, which we call Kwiz, is to answer movie-related questions based on movie posters (we use movie as a general term, which also includes series). After starting the game, players are shown a blurred image of a movie poster that increasingly unblurs over the course of a short time period.
As soon as players are ready to answer the question, they can tap the screen and are presented with a question related to the respective movie (e.g., “What is the name of the movie?”). The more seconds remain before tapping the screen, the more points users can collect with a correct answer. When guessing correctly, users can choose to double their points with a more challenging bonus question (e.g., “When was the movie released?”). Alternatively, users can collect their points and continue with the game until their lives have been depleted.
To incorporate exploration and learning, Kwiz presents users with a few key facts and trivia on a movie once the related questions have been completed. These facts include data from the main dataset (e.g., title and genre) as well as auxiliary data (e.g., movie posters).
This wiki describes the project (Kwiz) that we (Alex Scheitlin, Roland Schläfli, and Nik Zaugg) have worked on as part of our course on Advanced Software Engineering (Project Instructions) at the University of Zurich.
We use separate repositories for the different microservices and combine them, alongside several auxiliary repositories, in an umbrella repository that is used for documentation, project planning, and files that need to be shared across all services (e.g., docker-compose.yml).
The structure of the umbrella repository can be broken down as follows:
| Repository | Description | Quality |
|---|---|---|
| ionic-app | contains the sources for the application frontend | |
| nest-api | contains the sources for the GraphQL backend | |
| metadata-service | contains the sources for the service managing movie metadata | |
| poster-service | contains the sources for the service managing OMDB API requests | |
| kwiz-dotfiles | contains shared rulesets that make sure formatting and linting are consistent | |
| kwiz-utils | contains library code that is used in more than one service (DRY) | |
| kwizapp.github.io | contains the sources for https://kwizapp.github.io, our presentation deployment | |
| wiki | contains the documentation sources (the ones you are reading) in a .md format |
The following provides a short overview of our documentation structure:
| Topic | Description |
|---|---|
| Project Overview (current chapter) | Introduces our project and the datasets we have used to develop it, as well as the issues we still have on our roadmap. |
| Architecture | Describes the architecture of our microservice application and how we integrate everything into a single service. |
| Development | Describes how the project was planned, how we organized ourselves and explains how we applied a agile software development methodology. |
| Continuous Integration | Introduces and motivates the devops practices (as taught in the course) that we have applied to our project by means of automated systems, tooling, and workflows. |
| Reference | Provides an overview of all the APIs that we have developed for the purpose of our application. |
Datasets and APIs provide the backbone for the functionality of our application. Kwiz depends on two main sources of information:
Each of the data sources used in Kwiz is managed by a separate microservice. More specifically, the metadata-service returns metadata for a given movie whereas the poster-service returns a movie poster for a given IMDb ID.
More information on the structure of our microservices can be found in the Architecture section.
as published on Kaggle
This dataset contains several .csv files with metadata including 26 million ratings from 270,000 users for 45,000 movies. Ratings are on a scale of 1-5 and have been obtained from the official GroupLens website.
as exposed through an API
This API currently provides over 280,000 movie posters. It is a RESTful web service that can be accessed once an API Key has been generated.
as published on Kaggle
Initially, the plan was to use this dataset to self-distribute movie posters. After realizing that this dataset yields very low fidelity links to posters and does not provide a mapping of imdb-ids to posters, we decided to drop this dataset and opted for the above API instead.
main features and milestones
The main features of each milestones are also listed below.
completed: April 27th 2020
completed: May 22nd 2020
While we have finished an initial v1.0.0 of Kwiz, there are many ideas left to be implemented. We have added ideas for future work to a v2.0.0 milestone and dedicate this space to shortly introduce the most prominent ones.
Related Movies
Computing questions based on a set of related movies, rather than showing the movie in question alongside three randomly chosen movies, would provide the foundation for many other features (some of which are also described here).
Additional Question Types
Optionally, in the future, the current state of the game can be extended with additional question types by combining the existing dataset with more external datasets and API resources.
Such question types could allow for guessing...
Multiplayer Mode
Game Parameters
"Movie Ninja"
We decided on the following guidelines when working on design:
Based on our guidelines, we set out to develop mockups in Figma:
All of our mockups can be viewed directly on Figma.
While implementing the application, we continuously improved and evolved our design, yielding a much more consistent layout than imagined in the mockups:
Initial Assessment
The overall context of our application architecture, namely developing everything using web technologies, has been chosen such that all project members have some prior experience that they can apply to the project. Everyone on the team possesses significant knowledge on React development, and we all know how to work with TypeScript and popular Node.js frameworks. We also possess know-how on working with GraphQL, even though not everyone has worked with it before.
Out of personal interest to learn something new, we introduce two new frameworks into our application stack: Ionic and Nest.js. The introduction of Ionic allows us to develop mobile applications while applying our foundational knowledge of web technologies and React, while using Nest.js allows us to learn more about how a NodeJS API can be structured in a maintainable way.
Using these technologies incurs a level of risk in that we cannot definitively assess how much time will be spent on learning them and what features can or cannot be implemented using them. However, preliminary evaluation has shown that Ionic is very similar to normal React applications (besides its different build process)., and that Nest.js is structurally similar to well-known MVC frameworks like Java Spring. Therefore, our assessment is that it is well worth learning these new technologies to broaden our knowledge, even though there is a risk of additional time investment.
Team Kwiz, March 2020
Given that we chose to use a few new technologies, our initial assessment (as seen in the quote above) was quite optimistic. Now that we are about to conclude our project, we can say that we have mostly made good choices regarding technologies and processes. We would probably replace our frontend framework with React Native if we were to start over, as the Ionic framework, even though it is just web technologies, caused us a lot of frustration. While none of us has much experience with React Native, using it would probably result in a much more interesting and enjoyable development experience (but not necessarily in a "better" product).
For the remainder of our initial technical decisions, we have found that we would still approach them in the same way: our backend has been quite interesting to develop and the MVC approach gave the code a structure that is often missing in Node.js projects. Furthermore, the microservices have been very easy to develop and have caused almost no overhead due to the simplicity of the micro framework. We were able to get the microservices working very early on, which we attribute at least partly to our choice of technologies.
What we did not explicitly state in our initial assessment were the many procedural decisions that we had to make while working on the project (as described in depth in the remainder of this wiki). When looking at our working process and the continuous progress we were able to make, we identified a few key points that stand out:
Kwiz is a cross-platform application built using the Ionic framework and React. This allows for easy deployment to both web and mobile platforms without having to specifically optimize code for each deployment.
The backend of the application is based on Nest.js and communicates with the frontend using GraphQL. Both Ionic and Nest.js are based on Node.js and TypeScript, which enables a seamless switch between projects while sharing much of the auxiliary code for development and deployment.
The data backing the application is be provided by two microservices based on the minimal micro framework for Node.js. Each of these microservices provides different data related to movies. The metadata-service provides key information about movies and is connected to a postgres database. The poster-service on the other hand provides movie posters for specific IMDb IDs. This service has no database, but talks directly to another API (OMDB API). Both services expose a REST-API for data fetching. The backend will fetch data from these microservices independently and provide the game with all data through the unified GraphQL endpoint.
Applying a microservice architecture allows us to profit in several areas:
| Topic | Description |
|---|---|
| Ionic App | Describes the frontend of Kwiz, the Ionic App. |
| Nest API | Describes the main API of Kwiz, the Nest API. |
| Metadata Service | Describes one of the data sources for Kwiz. |
| Poster Service | Describes one of the data sources for Kwiz. |
The Ionic App is responsible for providing the user with the interface to our application. The Frontend is built using modern web technologies such as ReactJS and Typescript. Furthermore, we leverage the Ionic Framework, which is an
open source UI toolkit for building performant, high-quality mobile and desktop apps using web technologies. Ionic is the only mobile app stack that enables web developers to build apps for all major app stores and the mobile web from a single codebase.
The main idea behind the Ionic Framework is providing a reliable way to distribute software onto all major platforms by only writing code once. The Ionic Framework also provides a set of UI React Components that are specifically themed for the platform they are deployed to. This allows for fast prototyping and great developer experience, while still adhering to the design guidelines of the supported platforms (e.g., Android and iOS).
The Kwiz Ionic App is distributed as a Single Page Application (SPA). While bottlenecks could occur when many clients request the same (static) resources, we could then think about distributing the application onto various CDN nodes that are closer to the client.
The Nest API is responsible for fetching data from the Metadata Service and the Poster Service and is used by the Ionic App as the single source of data through the exposed GraphQL API. As the name suggests, the API uses Nest.js, which is
a progressive Node.js framework for building efficient, reliable and scalable server-side applications
The Nest application itself is stateless, meaning that incoming requests are answered by querying the two services for metadata and posters, structuring the data, and returning it whereby no information is stored persistently. Based on that and with the use of Docker, it is easy to scale the application.
While there are two REST services providing all the required data used for Kwiz, introducing this GraphQL API is advantageous because of the following reasons:
The Metadata Service provides an API for movie metadata, which includes properties like a movie's title, revenue, release date, and so on. The service is built using micro, a library that was specifically developed for asynchronous HTTP microservices. It is highly performant, simple to deploy, and very lightweight.
Micro — Asynchronous HTTP microservices
The data the API provides is stored in a Postgres Database, which we are currently hosting on Heroku. The Metadata Service itself is stateless, meaning that it does not depend on any particular state beside the database and can, therefore, be scaled easily. To hydrate the database, we wrote custom Python scripts that handle data cleaning, preprocessing, and hydrating the database.
The Poster Service provides an API that serves as an abstraction to the OMDB API. It is based on micro, a library specifically developed for asynchronous HTTP microservices. It is highly performant, simple to deploy, and very lightweight.
Micro — Asynchronous HTTP microservices
The Poster Service is stateless, meaning that it does not store any particular state and can, therefore, be scaled easily should it be necessary. The service only gets an IMDb-ID as a param and queries the OMDB API, after which it returns a high-fidelity poster path. We do not need any data from the OMDB API besides the poster path.
| Topic | Description |
|---|---|
| Project Planning | Describes the usage of user stories, issues, pull requests and the kanban board. |
| Version Control | Explains the workflow with git using branches, tags, squashing, and reviewing. |
| Dependency Management | Presents the tool we use to ensure the application uses the latest dependencies. |
High Level
master into dev)Once the development started, the following methodology was applied:
For this project we decided against using pre-defined sprints but to work in larger time spans - Milestones:
MVP - minimum viable product
v1.0.0 - stable version with all planned features for version 1.0.0
v2.0.0 - additional features
detailed descriptions of the features in each milestone can be found here
At the beginning of the project the following steps were taken to plan the work to be done:
Work distributions was generllay considered: "first come first served" - meaning that whenever you did not have any issue assigned to yourself, you could pick one from the board. Also, we did not split up our team into backend/frontend responsibilities. This worked well for everyone, as we already knew each other before the course and we were sure that everyone would contribute their share to the project.
Weekly Meetings: We held online meetings in Microsoft Teams each week to decide on which features to implement next and to talk about the current progress, eventual problems and challenges. These meetings were very valuable, as it helped us stay on track for the goals that we set for ouselves (Milestones).
In a next step, the GitHub Project was initialized with a Github Kanban Board. This step also involved having a meeting and writing User Stories, Issues and decide on the priority of each feature. In the end, we added the following user stories to the User Stories column.
Each user story has the same structure and includes multiple acceptance criteria. We enforced the structure by creating a Github Issue Template.
Before implementing any feature, issues regarding the feature needed to be created. For this, the user stories were split up into more fine-grained tasks which we tracked as Issues on our board. The issues also followed a predefined structure as specified in our organization wide Github Issue Template. Whenever there was a story that belonged to the issue, we added a reference to the original story in the issue description.

In a final step, the issue was labeled and added to the project board. From there, any of the team members could assign the issue to himself and start working on it.
The following screenshots show an outtake of a feature implementation, namely The Question Screen, which shows 4 possible options that the user can choose from (select which movie was shown before).
1. The issue is created and describes the criteria that need to be fulfilled
2. After implementing the feature, the Pull Request is created
3. Every merge into dev needs at least one approval. The PR is reviewed.
4. After making the requested changes, the PR can be merged. Multiple CI checks ensure good code quality.
We use Git to collaboratively work on the same code base and manage different releases of our code. GitHub is, among other things, used as a remote repository and to create an organization and structure for the different repositories of our application.
To manage changes to our source code, we use a simplified Gitflow Workflow.
More specifically, we apply the following procedures:
master branch serves as the release branch and is automatically deployed to production using Github Actions. Releases are tagged on the master branch to provide easy access to release snapshots.dev branch contains the latest changes to the source code that have been merged but not yet released. The dev branch is automatically deployed to a separate staging environment.dev or master branch have been disabled.Merging changes from feature branches to the dev branch or from the dev branch to the master branch involves making a pull request and going through a manual/automated review/approval cycle. Whenever possible, restrictions are enforced using settings in the Github interface.
feature -> dev)To merge a code change into the dev branch, the following restrictions apply for merges across the services:
check) are coherent with our guidelinesbuild_docker_hub) yields a valid imageWhen a feature branch is merged into the dev branch, it must be squashed to ensure a clean history on the dev and master branches.
dev -> master)In addition to all of the restrictions that apply for feature branches, the following additions apply:
Once a release has been merged into the master branch by means of a release PR (e.g., Release v1.0.1), a corresponding tag is created to make snapshots easily accessible.
While the crucial auxiliary repositories (kwiz-utils and kwiz-dotfiles) are subject to the same restrictions as listed above, less crucial ones apply relaxed procedures where PRs can be made directly against the master branch, and direct pushes can be permitted.

To ensure our project dependencies stay up-to-date, we use https://dependabot.com/ across all of our services. With this setup, it should, in principle, not be necessary to update dependencies manually (even though that might sometimes be more efficient).
Dependabot will perform a weekly check of all project dependencies and open a Pull Request for any dependencies that are outdated. As these pull requests include changelogs as well as links to all of the relevant resources, this procedure makes it very convenient to keep a project up-to-date.
While it would also be possible to have Dependabot automatically merge dependencies based on CI status and predefined rules, we have decided to manually approve any changes to our application dependencies.
One example of a Dependabot PR can be found here: https://github.com/kwizapp/ionic-app/pull/141
We use GitHub Actions to automate our workflow and build a continuous integration (CI) pipeline.
After adding changes to the source code and checking them into Git, the commits are pushed to GitHub. As soon as a pull request is opened the GitHub Action is triggered and the whole CI pipeline starts (only on PRs merging to the dev or master branch). First, quality checks are run, such as linting (ESLint) and formatting (Prettier) and using Sonarcloud to run different checks on the code (Sonarcloud). Then, all tests are run and the docker image gets built and pushed to Docker Hub. Once the PR is merged, the application is released on the appropriate Heroku deployment. Every step is only started if the previous one has succeeded.
The following table gives a brief overview of the steps involved in the CI pipeline. Read the respective sections to get detailed information about each step.
| Topic | Description |
|---|---|
| Code Quality | Shows how we ensure a high level of code quality using linters, static analysis and more. |
| Testing | Shows how we use unit and end-to-end tests for new features. |
| Build | Describes how we package our application with Docker. |
| Deployment | Explains the different types of deployments we use. |
Have a look at one of the GitHub Actions to see how the CI pipeline is configured (e.g., ionic-app).
To ensure a high level of source code quality, we use a bunch of different tools and techniques which are described below. As the source code of all repositories is written with TypeScript and JavaScript, most of the tools and techniques can be applied in all repositories.
We use different types of documentation for kwiz which are listed below. This ensures that people new to this repository can understand (i) what this application is about, (ii) how it was implemented, (iii) how it can be extended, and (iii) how it can be built and deployed.
kwiz application and provides all related documentation.
/**
* Build the URL to get information about a specific or one/multiple random
* movie(s) from the `MetadataService`.
*
* @param imdbId - The IMDb ID of the movie to fetch some metadata for.
* This parameter is optional. If it is not supplied, one or
* more random movies are returned.
* @param numMovies - The number of random movies to return.
* This parameter is optional and only considered if there
* is no IMDb ID given. If this parameter is not supplied,
* exactly one movie will be returned.
* @param differentFrom - An optional IMDb ID specifying a movie that should not be
* included in the returned movies. If it is not supplied,
* any movies can be returned.
* @param differentReleaseYear - An optional parameter specifying a year, in which
* non of the returned movies should be released in.
*/
export const buildMetadataServiceURL = (
imdbId: string = null,
numMovies: number = 1,
differentFrom: string = null,
differentReleaseYear: number = 0,
): string => {
...
};We apply appropriate ESLint rules across our projects to statically analyze the source code to find and fix problems. Moreover, we use Prettier to format the source code to ensure consistency across commits of different developers.
Both checks are automatically performed before every commit (locally) and also integrated in the CI pipeline.
To ensure consistency of linting and formatting rules across repositories, we have created an auxiliary repository with packages that contain configurations that we can reuse across the entire organization. See the packages for more information.
To ensure good code quality, we use the Sonarcloud platform to run static analysis on our code.
| Service | Maintainability |
|---|---|
| ionic-app | |
| nest-api | |
| metadata-service | |
| poster-service |
To work with uniform issue and pull request descriptions and to guarantee that every step of our workflow has been followed before new changes are introduced into the code base, we use custom Templates providing the structure and check lists for issues and pull requests. Amongst others, they require that tests haven been written/adjusted and that the documentation has been extended. Read more about testing here.
Our development process requires that only tested source code gets merged into the development branch (and later into the master branch). Thus, the pull request template on GitHub contains an item mentioning to write tests if necessary:
Have you added tests where necessary? Do all the test pass?
To ensure that the implemented source code works as expected, we use both unit and end-to-end (e2e) tests. We run the tests locally, after each push to a pull request with GitHub Action and before building and deploying the docker images and the application.
We use the testing framework Jest for both unit and e2e tests and supertest for the e2e tests to facilitate HTTP testing. To test the services of the nest-api we use Jest's mocking utilities.
Below are two examples of e2e tests testing the (i) REST API of the metadata-service and (ii) GraphQL API of the nest-api:
it('fetches a list of random movies filtered to be different from a given movie',
async () => {
const response = await request(micro(server)).get('/?numMovies=3&
differentFrom=tt0076759')
expect(response.statusCode).toEqual(200)
expect(response.body.length).toEqual(3)
response.body.forEach((movie) =>
expect(movie).toMatchObject({
date_segment: expect.any(String),
imdb_id: expect.any(String),
title: expect.any(String),
}),
)
expect(response.body.map((movie) => movie.imdb_id)).not.toContain('tt0076759')
})it('should return a specific movie with two random movies not released in the same
year as the specified movie', () => {
return request(app.getHttpServer())
.post('/graphql')
.send({
query: `{
movie(imdbId: "tt2395427") {
imdbId title releaseYear posterPath
randomMovies(num: 2, differentReleaseYear: true) {
imdbId title releaseYear posterPath
}
}
}`,
})
.expect(200)
.then((response) => {
const movie = response.body.data.movie
expect(movie.imdbId).toBe(MOVIE.imdbId)
expect(movie.title).toBe(MOVIE.title)
expect(movie.releaseYear).toBe(MOVIE.releaseYear)
expect(movie.posterPath).toBe(MOVIE.posterPath)
expect(movie.randomMovies.length).toBe(2)
let randomMovie = movie.randomMovies[0]
expect(randomMovie.imdbId).not.toBe(MOVIE.imdbId)
expect(randomMovie.title).not.toBe(MOVIE.title)
expect(randomMovie.releaseYear).not.toBe(MOVIE.releaseYear)
expect(randomMovie.posterPath).not.toBe(MOVIE.posterPath)
randomMovie = movie.randomMovies[1]
expect(randomMovie.imdbId).not.toBe(MOVIE.imdbId)
expect(randomMovie.title).not.toBe(MOVIE.title)
expect(randomMovie.releaseYear).not.toBe(MOVIE.releaseYear)
expect(randomMovie.posterPath).not.toBe(MOVIE.posterPath)
})
})After the CI Pipeline passed the linting and formatting checks and all tests have been executed successfully, the docker docker images are built and pushed to docker hub.
All micro-services are automatically deployed to Heroku as a last step of the continous integration pipeline. A new deployment will be triggered every time a pull request to one of the two main branches is made (either to dev or master).
Each deployment consists of the following steps:
Further there are two different types of deployments:
Staging Deployments
PRs to the dev branch trigger a staging deployment to the following heroku applications:
| Service | URL |
|---|---|
metadata-service |
https://kwiz-metadata-service-stage.herokuapp.com |
poster-service |
https://kwiz-poster-service-stage.herokuapp.com |
nest-api |
https://kwiz-nest-api-stage.herokuapp.com/graphql |
ionic-app |
https://kwiz-ionic-app-stage.herokuapp.com |
Production Deployments
PRs to the master branch trigger a staging deployment to the following heroku applications:
| Service | URL |
|---|---|
metadata-service |
https://kwiz-metadata-service.herokuapp.com |
poster-service |
https://kwiz-poster-service.herokuapp.com |
nest-api |
https://kwiz-nest-api.herokuapp.com/graphql |
ionic-app |
https://kwiz-ionic-app.herokuapp.com |
The production application is also available on https://kwizapp.github.io to demo the mobile app.
_Note that heroku dynos go to sleep after one hour of inactivity and need some time to wake up after the first request._
| Reference | Description |
|---|---|
| Components: Ionic App | Description of different pages and UI components |
| API Reference: Nest API | GraphQL API endpoints providing movie data and scoring functionality |
| API Reference: Metadata Service | REST endpoints providing information about movies |
| API Reference: Poster Service | REST endpoints providing URLs to movie posters |
The ionic-app is the frontend of the kwizapp and is built with ReactJS on top of the Ionic Framework.
The source code is divided into Pages and Components, this was a design choice made by the team as it helps to separate top-level components such as Home.tsx from more granular and reusable components such as the KwizButton.tsx.
This figure shows the top-level components and the user flow through the application.

We create documentation for all the react component right from the source code. For this, we use styleguidist to generate a static documentation page. E.g., for the AnswerCard.tsx component:

The documentation is published here: https://kwizapp.github.io/ionic-app/
The nest-api provides the following requests to:
All requests should be made to the /graphql endpoint (e.g., http://localhost:3000/graphql).
| Parameter | Type | Default | Description |
|---|---|---|---|
imdbId |
string |
- |
Optional. IMDb ID, uniquely identifies a movie. |
randomMovies |
field |
- |
Optional. Specifies that one or multiple additional random movie(s) should be returned. |
num |
int |
1 |
Optional. Specifies how many additional random movies should be returned. |
differentReleaseYear |
boolean |
false |
Optional. Specifies whether the random movie(s) should have a different release year than the specified one. |
Note:
imdbId is used, a specific movie is returned. If the parameter is not added, a random movie is returned.randomMovies is added but no num is specified, one additional random movie is returned. randomMovies can completely be omitted, so that no additional random moves are returned.differentReleaseYear is added but no imdbId is specified, differentReleaseYear will not be considered.Example
Request:
query {
movie(imdbId: "tt1431045") {
imdbId title releaseYear posterPath
randomMovies(num: 3, differentReleaseYear: true) { imdbId title releaseYear posterPath }
}
}Response:
{
"data": {
"movie": {
"imdbId": "tt1431045",
"title": "Deadpool",
"releaseYear": 2016,
"posterPath": "https://m.media-amazon.com/images/M/MV5BYzE5MjY1ZDgtMTkyNC00MTMyLThhMjAtZGI5OTE1NzFlZGJjXkEyXkFqcGdeQXVyNjU0OTQ0OTY@._V1_SX300.jpg",
"randomMovies": [
{
"imdbId": "tt1318514",
"title": "Rise of the Planet of the Apes",
"releaseYear": 2011,
"posterPath": "https://m.media-amazon.com/images/M/MV5BYzE3ZmNlZTctMDdmNy00MjMzLWFmZmYtN2M5N2YyYTQ1ZDJjXkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg"
},
{
"imdbId": "tt0076759",
"title": "Star Wars",
"releaseYear": 1977,
"posterPath": "https://m.media-amazon.com/images/M/MV5BNzVlY2MwMjktM2E4OS00Y2Y3LWE3ZjctYzhkZGM3YzA1ZWM2XkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_SX300.jpg"
},
{
"imdbId": "tt3896198",
"title": "Guardians of the Galaxy Vol. 2",
"releaseYear": 2017,
"posterPath": "https://m.media-amazon.com/images/M/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_SX300.jpg"
}
]
}
}
}| Parameter | Type | Description |
|---|---|---|
imdbId |
string |
IMDb ID, uniquely identifies a movie. This is the id of the blurred poster that was shown. |
selectedTitle |
string |
The title that was selected as the answer. |
remainingSeconds |
int |
The number of remaining seconds when the player tapped the screen to guess the movie title. |
Example
Request:
query {
scoreTitleResponse(
imdbId: "tt1431045",
selectedTitle: "Deadpool",
remainingSeconds: 5
)
}Response:
If the player scores zero points, the answer is incorrect and therefore one life is deducted.
{
"data": {
"scoreTitleResponse": 500
}
}| Parameter | Type | Description |
|---|---|---|
imdbIds |
[string] |
IMDb IDs, uniquely identifying movies. Ordered by release year in increasing order.* |
titleQuestionScores |
int |
The points scored in the "poster guessing" question. |
* This means that the player choses the order of the movie releases. The imdbIds are then sent to the API in this order. The API then checks whether they are sorted by their release years in increasing order.
Example
Request:
query {
scoreBonusResponse(
imdbIds: ["tt0145487", "tt0468569", "tt1431045"],
titleQuestionScores: 350
)
}Response:
If the answer is correct, the points are doubled. If the answer is incorrect, no points are awarded.
{
"data": {
"scoreBonusResponse": 700
}
}This service provides metadata for movies. The metadata-service API is simple and provides two main modes of operation:
ImdbID/?imdbId=<id>
| Parameter | Type | Default | Description |
|---|---|---|---|
imdbId |
ImdbID |
undefined | Optional. IMDb ID, uniquely identifies a movie. The service will return random movie(s) if the parameter is not given. |
Example:
http://localhost:3003/?imdbId=tt3450958
Returns:
[
{
"imdb_id": "tt3450958",
"budget": "152000000",
"homepage": "http://www.foxmovies.com/movies/war-for-the-planet-of-the-apes",
"original_language": "en",
"original_title": "War for the Planet of the Apes",
"overview": "Caesar and his apes are forced into a deadly conflict with an army of humans led by a ruthless Colonel. After the apes suffer unimaginable losses, Caesar wrestles with his darker instincts and begins his own mythic quest to avenge his kind. As the journey finally brings them face to face, Caesar and the Colonel are pitted against each other in an epic battle that will determine the fate of both their species and the future of the planet.",
"popularity": 146.161786,
"poster_path": "/3vYhLLxrTtZLysXtIWktmd57Snv.jpg",
"release_date": "2017-07-11",
"revenue": 369907963,
"runtime": 140,
"status": "Released",
"tagline": "For freedom. For family. For the planet.",
"title": "War for the Planet of the Apes",
"video": false,
"vote_average": 6.7,
"vote_count": 1675,
"release_year": 2017,
"date_segment": "2"
}
]/?numMovies=<MovieCount>&differentFrom=<OtherImdbID>¬ReleasedIn=<ReleaseYear>
| Parameter | Type | Default | Description |
|---|---|---|---|
numMovies |
Integer |
1 | Optional. Defines how many results should be fetched when fetching random movies. |
differentFrom |
ImdbID |
undefined | Optional. Defines a base ImdbID that will not be included in any random results. |
notReleasedIn |
Integer |
undefined | Optional. Defines a release year that movies in the random results should not be from. * |
* If notReleasedIn is specified, the random results will have distinct release years (i.e., the release year will be different from the specified release year and there will not be two random results having the same release year.).
This service is responsible for returning urls of movie poster images for a specific IMDb id. It acts as a middleware and talks directly to https://www.omdbapi.com/. From there it fetches the poster-url and returns it.
query
/?id=<id>&size=<size>
| Parameter | Type | Description |
|---|---|---|
id |
string |
Required. IMDb ID, unique to a film |
size |
number |
Optional. Size of the movie poster. Integer between [300, 1000] |
Fetching a Poster by ID
http://localhost:3002/?id=tt1477834
{
"poster": "https://m.media-amazon.com/images/M/MV5BOTk5ODg0OTU5M15BMl5BanBnXkFtZTgwMDQ3MDY3NjM@._V1_SX300.jpg"
}Fetching a Poster by ID with Size
http://localhost:3002/?id=tt3896198&size=450
{
"poster": "https://m.media-amazon.com/images/M/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_SX450.jpg"
}